package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.SecurityContext;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private RemoteProductService remoteProductService;

    private String getCarKey(Long userId) {
        //定义key user:userId:cart
        return "user:cart:" + userId;
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        //1.构建“用户”购物车hash结构key  user：用户ID：cart
        String carKey = getCarKey(userId);
        //2.创建Hash结构绑定操作对象（方便对hash进行操作）
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(carKey);
        //4.判断用户购物车中是否包含该商品 如果包含：数量进行累加(某件商品数量上限99) 不包含：新增购物车商品
        String hashkey = skuId.toString();
        Integer threahold = 99;
        if (hashOps.hasKey(hashkey)) {
            //4.1 说明该商品在购物车中已有，对数量进行累加 ，不能超过指定上限99
            CartInfo cartInfo = hashOps.get(hashkey);
            int totalCount = cartInfo.getSkuNum() + skuNum;
            cartInfo.setSkuNum(totalCount > threahold ? threahold : totalCount);
            hashOps.put(hashkey, cartInfo);
        } else {
            //3.判断购物车商品种类（不同SKU）总数大于50件
            Long count = hashOps.size();
            if (++count > 50) {
                throw new RuntimeException("商品种类数量超过上限！");
            }
            //4. 说明购物车没有该商品，构建购物车对象，存入Redis
            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuNum(skuNum > threahold ? threahold : skuNum);
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
            //4.1 远程调用商品服务获取商品sku基本信息
            R<ProductSku> productSku = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSku.getCode()) {
                throw new ServiceException(productSku.getMsg());
            }
            ProductSku data = productSku.getData();
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuName(data.getSkuName());
            cartInfo.setThumbImg(data.getThumbImg());
            cartInfo.setSkuPrice(data.getSalePrice());
            cartInfo.setCartPrice(data.getSalePrice());
            cartInfo.setIsChecked(1);
            //4.2 将购物车商品存入Redis
            hashOps.put(hashkey, cartInfo);
        }
    }

    @Override
    public List<CartInfo> cartList() {
        //获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        String carKey = this.getCarKey(userId);
        //获取数据
        List<CartInfo> values = redisTemplate.opsForHash().values(carKey);

        if (!CollectionUtils.isEmpty(values)) {
            List<CartInfo> cartInfos = values.stream().sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime())).toList();
            //获取skuid
            List<Long> skuIdList = cartInfos.stream().map(CartInfo::getSkuId).toList();
            //获取商品的实时价格
            R<List<SkuPrice>> skuPriceList = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if (R.FAIL == skuPriceList.getCode()) {
                throw new ServiceException(skuPriceList.getMsg());
            }
            //将商品sku价格转换成map
            Map<Long, BigDecimal> skuIdToPriceMap = skuPriceList.getData().stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            //更新商品最新价格：更新内存中商品最新价格，而不是购物车中价格。因为没有重新放回到购物车中。
            for (CartInfo cartInfo : cartInfos) {
                cartInfo.setSkuPrice(skuIdToPriceMap.get(cartInfo.getSkuId()));
            }
            return cartInfos;
        }
        return new ArrayList<>();
    }

    @Override
    public void deleteCart(Long skuId) {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        //获取缓存对象
        String carKey = getCarKey(userId);
        BoundHashOperations hashOps = redisTemplate.boundHashOps(carKey);
        hashOps.delete(skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        //获取缓存对象 // 修改缓存
        String carKey = getCarKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(carKey);
        if (hashOps.hasKey(skuId.toString())) {
            // 先获取用户选择的商品
            CartInfo cartInfo = hashOps.get(skuId.toString());
            // cartInfo 写入缓存
            cartInfo.setIsChecked(isChecked);
            // 更新缓存
            hashOps.put(skuId.toString(), cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        //获取缓存对象 // 修改缓存
        String carKey = getCarKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(carKey);
        System.out.println("hashOps = " + hashOps);

        List<CartInfo> values = hashOps.values();
        System.out.println("values = " + values);

        for (CartInfo value : values) {
            System.out.println("value = " + value);
            CartInfo cartInfo = hashOps.get(value.getSkuId().toString());

            System.out.println("cartInfo = " + cartInfo);
            cartInfo.setIsChecked(isChecked);

            hashOps.put(value.getSkuId().toString(), cartInfo);
        }

    }

    @Override
    public void clearCart() {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        //获取缓存对象 // 修改缓存
        String carKey = getCarKey(userId);
        //清空大Key
        redisTemplate.delete(carKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        //获取缓存对象 // 修改缓存
        String carKey = getCarKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(carKey);
        List<CartInfo> values = hashOps.values();
        if (!CollectionUtils.isEmpty(values)) {
            List<CartInfo> cartInfos = values.stream().filter(value -> value.getIsChecked() == 1).toList();
            return cartInfos;
        }
        return new ArrayList<>();
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        //获取redis中用户的购物车信息
        String carKey = getCarKey(userId);
        BoundHashOperations hashOps = redisTemplate.boundHashOps(carKey);
        List<CartInfo> values = hashOps.values();
        //判断购物车内信息是否为空
        if (!CollectionUtils.isEmpty(values)) {
            //选取购物车内选中的信息
            List<CartInfo> cartInfos = values.stream().filter(value -> value.getIsChecked() == 1).toList();
            //选取购物车内选中的信息 是否为空
            if (!CollectionUtils.isEmpty(cartInfos)) {
                //从购物车信息中 获取skuid list
                List<Long> skuIds = cartInfos.stream().map(cartInfo -> cartInfo.getSkuId()).toList();
                //远程调用 购物车批量查询价格列表接口 获取数据库中价格列表
                R<List<SkuPrice>> skuPriceList = remoteProductService.getSkuPriceList(skuIds, SecurityConstants.INNER);
                //判断远程调用获取的信息是否异常
                if (R.FAIL==skuPriceList.getCode()) {
                    throw new ServiceException(skuPriceList.getMsg());
                }
                //获取远程调用 数据库 封装结果的data
                List<SkuPrice> SkuPriceDataDB = skuPriceList.getData();
                //将data内 skuid 与对应价格 封装成map
                Map<Long, BigDecimal> PriceDBToMap = SkuPriceDataDB.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
                //循环购物车内商品信息 依次 设置 数据库中对应的价格 放入redis
                for (CartInfo cartInfo : cartInfos) {
                    BigDecimal newPrice = PriceDBToMap.get(cartInfo.getSkuId());
                    cartInfo.setSkuPrice(newPrice);
                    cartInfo.setCartPrice(newPrice);
                    hashOps.put(cartInfo.getSkuId().toString(),cartInfo);
                }
                return true;
            }
        }
        return false;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        //获取redis中用户的购物车信息
        String carKey = getCarKey(userId);
        BoundHashOperations hashOps = redisTemplate.boundHashOps(carKey);
        List<CartInfo> values = hashOps.values();
        //判断购物车内信息是否为空
        if (!CollectionUtils.isEmpty(values)) {
            //循环遍历 依次操作每个属性
            for (CartInfo value : values) {
                // 获取选中的商品！
                if (value.getIsChecked().intValue()==1) {
                    //删除选中信息
                    hashOps.delete(value.getSkuId().toString());
                }
            }

        }

        return null;
    }
}